import request from '@system.request'
import file from '@system.file'
import storage from './Storage';
import prompt from '@system.prompt'
import fetch from '@system.fetch'
import regeneratorRuntime from "@babel/runtime/regenerator";

//规则文件mock数据
import ruleFile from "./rule.json"

export default class Engine {
    constructor(app) {
        this.ruleUrl = "http://192.168.123.181:8080/rule1.json"
        this.localKey = "bookRule"
        this.activeRule = "activeRule"
        this.filePath = "internal://files/"
        this.ruleName = "rule.json"
        this.appData = app
        this.mockData = true
    }

    //下载网络文件
    async getDownFile(url) {
        try {
            let token = await this.downFile(url)
            let uri = await this.getDownUri(token)
            let charset = await this.getFileCharset(uri)
            let content = await this.readFileContent(uri, charset)
            this.delFile(uri)
            return content
        } catch (error) {
            prompt.showToast({
                message: error.data
            })
            console.log(error.data)
        }
    }

    //获取网络html内容
    async getHtmlContent(url) {
        try {
            let resp = await fetch.fetch({
                url: url,
                responseType: 'text'
            })
            return this.removeScript(resp.data.data)
        } catch (error) {
            console.log(error)
        }
    }

    async downFile(url, filename = '') {
        try {
            const resp = await request.download({
                url: url,
                filename: filename
            })
            return resp.data.token
        } catch (error) {
            return '文件地址错误'
        }
    }

    //下载文件的uri
    async getDownUri(token) {
        try {
            const resp = await request.onDownloadComplete({
                token: token
            })
            return resp.data.uri
        } catch (error) {
            return '文件下载失败'
        }
    }

    //======== 文件操作 ========
    //获取文件charset
    async getFileCharset(uri) {
        try {
            const resp = await file.readText({
                uri: uri
            })
            let reg = /charset="?(.*?)"/
            let charset = reg.exec(resp.data.text)
            return charset[1]
        } catch (error) {
            return error
        }
    }

    //读取文件
    async readFileContent(uri, charset = "utf-8") {
        const resp = await file.readText({
            uri: uri,
            encoding: charset
        })
        return resp.data.text
    }

    //删除文件
    async delFile(uri) {
        file.delete({
            uri: uri,
            success: function (data) {
                console.log('handling success')
            },
            fail: function (data, code) {
                console.log(`handling fail, code = ${code}`)
            }
        })
    }

    //是否更新规则文件
    async upateRule() {
        try {
            let resp = await fetch.fetch({
                url: this.appData.ruleFileUrl,
                data: this.appData.ruleParam,
                responseType: 'json'
            })
            return resp.data
        } catch (error) {

        }
    }

    //下载规则文件
    async downRuleFile() {
        let local = new storage("ruleVersion")
        let version = await local.get()
        let resp = await this.upateRule()
        console.log("我要下载", resp)
        let data = resp.data
        if (data.status == 200) {
            let urlData = data.data[0]
            let updateVersion = urlData.txt_ver
            if (version == null || updateVersion > version) {
                // console.log("我要下载",urlData.txt_url)
                local.set(updateVersion)
                let token = await this.downFile(urlData.txt_url, this.ruleName)
                let uri = await this.getDownUri(token)
                await this.readFileContent(uri)
                await this.moveRuleFile()
            }
        }
    }

    //移动文件到files目录
    async moveRuleFile() {
        try {
            let uri = this.filePath + this.ruleName
            await file.move({
                srcUri: 'internal://mass/download/' + this.ruleName,
                dstUri: uri,
            })
        } catch (error) {
            return error
        }
    }

    //读取规则文件内容
    async readRuleContent() {
        if (this.mockData) {
            return ruleFile
        } else {
            let url = this.filePath + this.ruleName
            let content = await this.readFileContent(url)
            return JSON.parse(content)
        }

    }

    //获取匹配小说网站规则
    async getDomainRule(url) {
        url = this.matchDomain(url)
        let resp = await this.readRuleContent()
        let rule = resp.find(item => {
            let itemUrl = this.replaceUrl(item.bookSourceUrl)
            return itemUrl == url
        })
        if (rule == undefined) {
            return false
        } else {
            let ruleData = Object.assign(rule, {
                isModel: true
            })
            return ruleData
        }
    }

    //

    //replace处理网址
    replaceUrl(url) {
        return url.replace(/(http:\/\/|https:\/\/).*?\./g, "")
    }

    //小说站网址获取
    matchDomain(url) {
        return this.replaceUrl(this.getDomain(url));
    }

    getDomain(url) {
        let reg = /(\w+):\/\/([^/:]+)(:\d*)?/g;
        let domain = url.match(reg);
        return domain[0]
    }

    //进入阅读模式 判断是内容页还是目录
    isOpenRead(url) {
        url = url.replace(/(\w+):\/\/([^/:]+).*?/g, "")
        url = url.replace(/(\.html|\.htm)/, "")
        url = url.replace(/^\/|\/$/g, '')
        var urlArr = url.split("/").slice(-2)
        var regx = /^\d+/g
        console.log(urlArr)
        return {
            isCatalog: urlArr.length == 1,
            isOpen: regx.test(urlArr.join(""))
        }
    }

    //转换规则文件为正则


    //正则规则
    removeScript(data) {
        return data.replace(/<script[^>]*>([\s\S](?!<script))*?<\/script>/ig, "")
    }

    string2Regx(data, isContent = false) {
        var stringArr = data.split("@")
        let ruleArr = []
        let lastRule = stringArr.pop()
        stringArr.map((item, index) => {
            let r = item.split(".")
            let regx
            if (r[0] == "tag") {
                if (index == stringArr.length - 1) {
                    if (lastRule == "text") {
                        regx = `<${r[1]}.*?>((\s|.)*?)<\/${r[1]}>`
                    } else {
                        regx = `<${r[1]}.*?${lastRule}.*?=.*?"(.*)">((\s|.)*?)<\/${r[1]}>`
                    }
                } else {
                    regx = `<${r[1]}.*?>((\s|.)*?)<\/${r[1]}>`
                }
                ruleArr.push({
                    regx: regx,
                    index: r[2] ? Number(r[2]) : r.length - 1
                })
            } else {
                if (r[0] == "tag") {
                    regx = `<${r[1]}.*?>(((\s|.))*?)<\/${r[1]}>`
                } else {
                    if (isContent) {
                        ruleArr.push({
                            regx: `${r[0]}.*?=.*?"${r[1]}".*?>((\\s|.)*?)<\/div`,
                            index: r[2] ? Number(r[2]) : 0
                        })
                    } else {
                        ruleArr.push({
                            regx: `${r[0]}.*?=.*?"${r[1]}".*?>((\\s|.)*?)<\/(div|nav|p|ul)`,
                            index: r[2] ? Number(r[2]) : 0
                        })
                    }

                }

            }
        })
        return ruleArr
    }


    //获取章节内容及页码导航
    async getCataLogContent(url) {
        let domain = this.getDomain(url)
        let activeRule = this.appData.activeBookRule
        let ruleArr = await this.string2Regx(activeRule.ruleChapterList)
        let source = await this.getHtmlContent(url)

        //页码
        let nav = await this.getNavLink(source, domain, "ruleChapterUrlNext")
        //章节
        var catalogList = []
        ruleArr.map((item, index) => {
            let regx = new RegExp(item.regx, 'gi');
            if (index == ruleArr.length - 1) {
                var r = "";
                while (r = regx.exec(source)) {
                    catalogList.push({
                        url: domain + r[1],
                        text: r[2]
                    })
                }
            } else {
                source = source.match(regx)[item.index]
            }
        })
        return {
            content: catalogList,
            nav: nav
        }

    }

    async getBookContent(url) {
        let domain = this.getDomain(url)
        let activeRule = this.appData.activeBookRule
        let ruleArr = await this.string2Regx(activeRule.ruleBookContent, true)
        let regx = new RegExp(ruleArr[0].regx, 'gi')
        let source = await this.getHtmlContent(url)
        let content = regx.exec(source)[1]
        //章节名称
        let name = await this.getBookName(source)
        //页码
        let nav = await this.getNavLink(source, domain, "ruleContentUrlNext")
        return {
            name: name,
            content: content,
            nav: nav
        }
    }

    async getNavLink(source, domain, navAttr) {
        let prev, next, catalog
        let activeRule = this.appData.activeBookRule
        let ruleArr = await this.string2Regx(activeRule[navAttr])
        let navRule = ruleArr[0]
        let regx = new RegExp(navRule.regx, 'gi')
        let navContent = source.match(regx)[navRule.index]
        navContent = navContent.replace(/[\r\n]/g, "").replace(/[\s+]/g, " ")
        let navRegx = /<a.*?href.*?=.*?"(.*?)".*?>.*?(上一页|下一页|上一章|下一章|目.*?录|书.*?页).*?<\/a>/ig
        let navMatch = navContent.match(navRegx)
        navMatch.map(item => {
            let aRegx = /<a.*?href.*?=.*?"(.*?)".*?>.*?<\/a>/ig
            if (item.indexOf("上") > -1) {
                prev = aRegx.exec(item)[1]
            }
            if (item.indexOf("下") > -1) {
                next = aRegx.exec(item)[1]
            }
            if (item.indexOf("录") > -1) {
                catalog = aRegx.exec(item)[1]
            }
        })
        return {
            prev: prev ? domain + prev : '',
            next: next ? domain + next : '',
            catalog: catalog ? domain + catalog : ''
        }
    }

    async getBookName(source) {
        let activeRule = this.appData.activeBookRule
        let ruleArr = await this.string2Regx(activeRule.ruleBookName)
        let navRule = ruleArr[0]
        let regx = new RegExp(navRule.regx, 'gi')
        let content = regx.exec(source)[1]
        return content
    }


    async getRule() {

    }

    async saveRule() {

    }
}